﻿using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using Shoozla.DataModel;
using Shoozla.DataModel.Helper;


namespace Shoozla.ViewModel
{
    public class FolderListViewModel : ViewModelBase
    {

        private string _selectedFolder = String.Empty;

        #region Constructors
        public FolderListViewModel(System.Windows.Threading.Dispatcher dispatcher) : base(dispatcher) { }
        #endregion

        #region Commands

        private RelayCommand _CmdShowAll;
        public RelayCommand CmdShowAll
        {
            get
            {
                if (_CmdShowAll == null)
                {
                    _CmdShowAll = new RelayCommand(param => DoCmdShowAll(), param => CanExecuteCurrentItemsOp());
                }
                return _CmdShowAll;
            }
        }

        private RelayCommand _CmdShowCovered;
        public RelayCommand CmdShowCovered
        {
            get
            {
                if (_CmdShowCovered == null)
                {
                    _CmdShowCovered = new RelayCommand(param => DoCmdShowCovered(), param => CanExecuteCurrentItemsOp());
                }
                return _CmdShowCovered;
            }
        }

        private RelayCommand _CmdShowUnCovered;
        public RelayCommand CmdShowUnCovered
        {
            get
            {
                if (_CmdShowUnCovered == null)
                {
                    _CmdShowUnCovered = new RelayCommand(param => DoCmdShowUnCovered(), param => CanExecuteCurrentItemsOp());
                }
                return _CmdShowUnCovered;
            }
        }


        #endregion

        #region Do Commands

        protected void DoCmdShowAll()
        {

            var currentFolderSelection = (from mp3 in App.AllItems
                                          where mp3.FileName.DirectoryName == _selectedFolder
                                          select mp3).ToList<Mp3File>();

            CurrentItems.ReplaceCollection(currentFolderSelection);
        }

        private void DoCmdShowCovered()
        {
            var currentFolderSelection = (from mp3 in App.AllItems
                                          where mp3.FileName.DirectoryName == _selectedFolder && mp3.HasCover == true
                                          select mp3).ToList<Mp3File>();

            CurrentItems.ReplaceCollection(currentFolderSelection);
        }

        private void DoCmdShowUnCovered()
        {
            var currentFolderSelection = (from mp3 in App.AllItems
                                          where mp3.FileName.DirectoryName == _selectedFolder && mp3.HasCover == false
                                          select mp3).ToList<Mp3File>();

            CurrentItems.ReplaceCollection(currentFolderSelection);
        }
    
        public void RefreshOpenedFolder()
        {
            MainWindowViewModel mainModel = ((MainWindowViewModel)App.MainView.DataContext);
            OpenFolderInternal(mainModel.RootFolder.FullName);
        }

        public void LoadMp3FromFolder(string folderName)
        {
            OpenFolderInternal(folderName);
        }

        //+ reading files from disk
        private void OpenFolderInternal(string folderName)
        {
            try
            {
                _selectedFolder = folderName;
                if (!App.ReadMp3Folders.Contains(folderName))
                {
                    App.ReadMp3Folders.Add(folderName);
                    DirectoryInfo dir = new DirectoryInfo(folderName);                    
                    FileInfo[] files = dir.GetFiles("*.mp3", SearchOption.TopDirectoryOnly);
                    if (files.Length == 0) {
                        CurrentItems.Clear();
                        return;
                    }

                    App.Logger.FilesProcessed = 0;

                    App.CurrentAppStatus = App.AppStatus.ReadingFiles;
                    RaiseItemOperationStarted(files.Length, "Searching for Mp3 files");//init the progress bar

                    //new folder added to the UI, triggering the Mp3 scanning and saving the file in cache
                    Cursor.Current = Cursors.WaitCursor;
                    Task backgroundFileReaderTask = Task.Factory.StartNew(() =>
                    {
                        ParallelOptions paralleSettings = new ParallelOptions();
                        paralleSettings.CancellationToken = App.MainCancellationTokenSource.Token;
                        paralleSettings.MaxDegreeOfParallelism = ThreadHelper.CalculateTreads(files.Length, ThreadingFactorEnum.Maximum);
                        Parallel.ForEach(files, paralleSettings, f => FileReader(f));
                      //  foreach (FileInfo f in files)
                      //      FileReader(f);
                    },App.MainCancellationTokenSource.Token);                  

                    
                    ////backgroundFileReaderTask.Wait(App.MainCancellationTokenSource.Token);
                    //_selectedFolder = folderName;
                    //FolderRead();
                   

                    Task.Factory.ContinueWhenAll(new Task[] { backgroundFileReaderTask }, (x) =>
                        {
                            _selectedFolder = folderName;
                            App.CurrentAppStatus = App.AppStatus.Idle;
                            FolderRead();
                            Cursor.Current = Cursors.Arrow;
                            RaiseItemOperationFinished();
                        });                                   
                }
                else
                {
                    //folder already read just refresh the view
                     _selectedFolder = folderName;
                    FolderRead();
                    
                }
            }
            catch (UnauthorizedAccessException accEx)
            {
                App.LogEntry("[ERROR] OpenFolderInternal: " + accEx.Message);
            }
        }

        private void FolderRead()
        {
           if (App.CurrentAppStatus == App.AppStatus.Idle)
                {
                    //folder already read just refresh the view
                    var currentFolderSelection = (from mp3 in App.AllItems
                                                  where mp3.FileName.DirectoryName == _selectedFolder
                                                  select mp3).ToList<Mp3File>();

                    CurrentItems.ReplaceCollection(currentFolderSelection);              
                    
                }
                else
                    System.Windows.MessageBox.Show("Shoozla is still working, wait for the completation of the previous operation","Shoozla");                
           
        }

        private void FileReader(FileInfo fi)
        {
            Mp3File song = App.Mp3Processor.ReadID3Tag(fi);
            if (song != null)
            {
                song.IsSelected = !song.HasCover; //select all "uncovered album"
                App.AllItems.Add(song);
            }
            RaiseItemRead();
        }
        #endregion

        private void SearchSingleCover(Mp3File song)
        {
            Uri coverUri = App.CoverSearcher.FindSingleCover(song);
            if (coverUri != null)
                song.ImageUrl = coverUri;       
            RaiseItemRead();
        }

    }
}
